#include "stm32f4xx.h"
#include "delay.h"
#include "uart.h"
#include "i2c1.h"
#include "bq76920.h"
#include "timer.h"
#include "calculate_soc.h"
#include "oled.h"
#include "string.h"
#include "kalmanfilter.h"

BQ76920_t bq_data;
KF_t kf_data;
extern float soc_ocv;
extern float soc_ah;
extern float soc_kf;
uint8_t reg_data;
uint8_t i;
uint8_t OV_flag;
uint8_t UV_flag;
uint8_t OC_flag;
uint8_t OT_flag;
uint8_t anyOV;
uint8_t anyUV;

char oled_buf[16];

int main(void)
{
    OLED_Init();
    OLED_Clear();
    OLED_ShowString(1, 1, "Battery");
    OLED_ShowString(2, 1, "Management");
    OLED_ShowString(3, 1, "System");
    OLED_ShowString(4, 1, "......");

    Uart_Init(115200);
    I2C1_Init();
    BQ76920_Init(&bq_data);
    TimerNvic_Config();
    TIM2_Config(2500, 7200);  // 250ms,update voltage,current
    TIM3_Config(20000, 7200); // 2s,update temperature
    Delay_ms(1000);
    OCVCalculateSOC(bq_data.cellVoltage);
    printf("SOC_OCV:%.2f%%\r\n", soc_ocv * 100);
    kalman_filter_init(&kf_data, soc_ocv, 0.01, 0.1, 1.0);
    TIM4_Config(10000, 7200); // 1s,update SOC
    Delay_ms(1000);

    while (1)
    {
        printf("-----Begin-----\r\n");
        BQ76920_PrintInfo(&bq_data);
        printf("SOC_AH:%.2f%%\r\n", soc_ah * 100);
        printf("SOC_KF:%.2f%%\r\n", soc_kf * 100);
        printf("------End------\r\n\r\n");

        OLED_Clear();
        sprintf(oled_buf, "Vcell%d:%dmV", 1, bq_data.cellVoltage[0]);
        OLED_ShowString(1, 1, oled_buf);

        sprintf(oled_buf, "Vcell%d:%dmV", 2, bq_data.cellVoltage[1]);
        OLED_ShowString(2, 1, oled_buf);

        sprintf(oled_buf, "Vcell%d:%dmV", 3, bq_data.cellVoltage[2]);
        OLED_ShowString(3, 1, oled_buf);

        sprintf(oled_buf, "Vcell%d:%dmV", 4, bq_data.cellVoltage[3]);
        OLED_ShowString(4, 1, oled_buf);

        Delay_ms(1000);

        OLED_Clear();
        sprintf(oled_buf, "Vcell%d:%dmV", 5, bq_data.cellVoltage[4]);
        OLED_ShowString(1, 1, oled_buf);

        sprintf(oled_buf, "Current:%.2fmA", bq_data.current);
        OLED_ShowString(2, 1, oled_buf);

        sprintf(oled_buf, "Temp:%.2fC", bq_data.TsTemp);
        OLED_ShowString(3, 1, oled_buf);

        sprintf(oled_buf, "SOC:%.2f%%", soc_ah * 100);
        OLED_ShowString(4, 1, oled_buf);

        for (i = 0; i < BQ76920_CELL_NUM; i++)
        {
            if (bq_data.cellVoltage[i] > TLB_OV_PROTECT * 1000)
            {
                anyOV = 1;
                break;
            }
        }
        if (anyOV == 1)
        {
            BQ76920_CloseCHG(&bq_data);
            OV_flag = 1;
            anyOV   = 0;
        }

        if (OV_flag == 1)
        {
            for (i = 0; i < BQ76920_CELL_NUM; i++)
            {
                if (bq_data.cellVoltage[i] > TLB_OV_RELIEVE * 1000)
                {
                    anyOV = 1;
                    break;
                }
            }

            if (!anyOV)
            {
                BQ76920_WriteRegister(SYS_STAT, 0xFF);

                BQ76920_OpenCHG(&bq_data);
                OV_flag = 0;
            }
        }

        for (i = 0; i < BQ76920_CELL_NUM; i++)
        {
            if (bq_data.cellVoltage[i] < TLB_UV_PROTECT * 1000)
            {
                anyUV = 1;
                break;
            }
        }
        if (anyUV == 1)
        {
            BQ76920_CloseDSG(&bq_data);
            UV_flag = 1;
            anyUV   = 0;
        }

        if (UV_flag == 1)
        {
            for (i = 0; i < BQ76920_CELL_NUM; i++)
            {
                if (bq_data.cellVoltage[i] < TLB_UV_RELIEVE * 1000)
                {
                    anyUV = 1;
                    break;
                }
            }

            if (!anyUV)
            {
                BQ76920_WriteRegister(SYS_STAT, 0xFF);

                BQ76920_OpenDSG(&bq_data);
                OV_flag = 0;
            }
        }

        if ((bq_data.current > 2000))
        {
            BQ76920_CloseDSG(&bq_data);

            OC_flag = 1;
        }
        if (OC_flag == 1)
        {
            if ((bq_data.current < 1500))
            {
                BQ76920_WriteRegister(SYS_STAT, 0xFF); // clear status

                BQ76920_OpenDSG(&bq_data);
                OC_flag = 0;
            }
        }

        if (bq_data.TsTemp > 35)
        {
            BQ76920_CloseDSGAndCHG();

            OT_flag = 1;
        }
        if (OT_flag == 1)
        {
            if ((bq_data.TsTemp < 34))
            {
                BQ76920_WriteRegister(SYS_STAT, 0xFF); // clear status

                BQ76920_OpenDSGAndCHG();
                OT_flag = 0;
            }
        }

        Delay_ms(1000);
    }
}
